<template>
  <div class="x-input-tag">
    <template v-if="tags && tags.length && tags[0]">
      <ElTag
        v-for="(tag, index) in tags"
        :key="tag.id || tag"
        size="medium"
        disable-transitions
        :closable="!inputDisabled"
        @close="handleClose(tag, index)">
        {{ tag.name || tag }}
      </ElTag>
    </template>
    <template v-else-if="inputDisabled">
      <span style="margin-left: 8px; color: #b5b5b5; line-height: normal">无</span>
    </template>
    <ElInput
      v-if="!inputDisabled"
      v-show="inputVisible"
      ref="saveTagInput"
      v-model="inputValue"
      class="input-new-tag"
      size="mini"
      @keyup.enter.native="handleInputConfirm"
      @blur="handleInputConfirm" />
    <ElButton
      v-if="!inputDisabled && !inputVisible"
      v-show="tags.length < maxTag"
      class="button-new-tag"
      size="mini"
      @click="showInput">
      + 添加
    </ElButton>
    <span v-if="count" class="tags-count">{{ tags.length && tags[0] ? tags.length : '' }}</span>
  </div>
</template>

<script>
  export default {
    name: 'XInputTag',
    inject: {
      elForm: {
        default: ''
      },

      elFormItem: {
        default: ''
      }
    },
    props: {
      value: {
        type: [Array, String],
        default: () => []
      },
      disabled: Boolean,
      separator: {
        type: String,
        default: ','
      },
      count: {
        type: Boolean,
        default: true
      },
      arrayMode: {
        type: Boolean,
        default: true
      },
      objectMode: {
        type: Boolean,
        default: true
      }
    },
    data() {
      return {
        inputVisible: false,
        inputValue: '',
        maxTag: 20
      }
    },
    computed: {
      inputDisabled() {
        return this.disabled || (this.elForm || {}).disabled
      },
      tags: {
        get() {
          if (this.arrayMode) {
            if (this.value?.length) {
              if (this.objectMode) {
                return this.value.map(value => {
                  if (value.id > 0) {
                    return value
                  } else {
                    return { ...value, id: Math.random() }
                  }
                })
              } else {
                return this.value
              }
            } else {
              return []
            }
          } else {
            const arr = this.value?.split(this.separator) || []
            return arr.length && arr[0]
              ? arr.map(item => (this.objectMode ? { name: item, id: Math.random() } : item))
              : []
          }
        }
      }
    },
    methods: {
      async showInput() {
        this.inputVisible = true
        await this.$nextTick()
        this.$refs.saveTagInput.$refs.input.focus()
      },
      handleClose(tag) {
        const tags = this.tags.filter(value => value !== tag)
        this.$emit('input', this.arrayMode ? tags : tags.map(value => value.name || value).join(this.separator))
      },
      async handleInputConfirm() {
        if (this.tags.length >= this.maxTag) {
          this.$message.warning({ message: '标签已达上限,请删除一些标签再添加！', showClose: true })
          this.inputVisible = false
          this.inputValue = ''
          return
        }
        const inputValue = this.inputValue
        if (inputValue) {
          if (this.tags.some(tag => (tag.name || tag) === inputValue)) {
            this.inputVisible = false
            this.inputValue = ''
            this.$message.warning({ message: '标签已存在！', showClose: true })
            return
          }
          const tags = [...this.tags]
          tags.push(this.objectMode ? { id: Date.now(), name: this.inputValue } : this.inputValue)
          this.$emit('input', this.arrayMode ? tags : tags.map(value => value.name || value).join(this.separator))
          await this.$nextTick()
          this.elFormItem?.clearValidate()
        }
        this.inputVisible = false
        this.inputValue = ''
      }
    }
  }
</script>

<style lang="scss">
  .el-form-item {
    &.is-error {
      .x-input-tag {
        border-color: #f56c6c;
      }
    }
  }

  .x-input-tag {
    position: relative;
    height: 120px;
    padding-top: 4px;
    padding-right: 4px;
    overflow: auto;
    line-height: 0;
    border: 1px solid var(--border-color);
    border-radius: 4px;

    .el-tag .el-tag__close:hover {
      background-color: #ee8677;
    }

    .el-tag {
      margin-bottom: 4px;
      margin-left: 4px;
    }

    .button-new-tag {
      margin-bottom: 4px;
      margin-left: 4px;
    }

    .el-input.input-new-tag {
      width: 120px;
      margin-bottom: 4px;
      margin-left: 4px;
    }

    .tags-count {
      position: absolute;
      right: 6px;
      bottom: 10px;
      color: #b7b7b7;
      font-size: 0.9em;
    }
  }
</style>
